package com.weixing.mall.provider.auth.sys;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.wrapper.ResultUtil;
import com.weixing.mall.provider.util.UaaUtil;
import com.weixing.oauth2.common.support.SecuritySupportHandler;
import com.weixing.oauth2.common.userdetails.IUserAuthService;
import com.weixing.oauth2.common.userdetails.SecurityUser;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Base64;


/**
 * 登录认证成功处理器.
 *
 * @author paascloud.net@gmail.com
 */
@Component("sysAuthenticationSuccessHandler")
@Slf4j
public class SysAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Resource
    private ObjectMapper objectMapper;
    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private SecuritySupportHandler securitySupportHandler;

    @Autowired
    @Qualifier("sysUserAuthService")
    private IUserAuthService sysUserAuthService;



    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException {

        logger.info("登录成功");

        String header = request.getHeader(HttpHeaders.AUTHORIZATION);

        if (header == null && !header.startsWith(GlobalConstant.BASIC_AUTH)) {
            throw new UnapprovedClientAuthenticationException("请求投中无client信息");
        }
        String[] tokens = UaaUtil.extractAndDecodeHeader(header);

        assert tokens.length == 2;

        //获取clientId 和 clientSecret
        String clientId = tokens[0];
        String clientSecret = tokens[1];

        //获取 ClientDetails
        ClientDetails clientDetails = getClient(clientId, clientSecret, clientDetailsService);
        // 生成jwt token
        TokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_MAP, clientId, clientDetails.getScope(), "customer");
        OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
        OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
        OAuth2AccessToken oAuth2AccessToken = securitySupportHandler.createAccessToken(oAuth2Authentication);
        oAuth2Authentication.setAuthenticated(true);
        // 处理登录后操作
        sysUserAuthService.handlerLoginData(request, (SecurityUser) authentication.getPrincipal());

        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write((objectMapper.writeValueAsString(ResultUtil.success(oAuth2AccessToken))));
    }


    private ClientDetails getClient(String clientId, String clientSecret, ClientDetailsService clientDetailsService) {
        ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
        if (clientDetails == null) {
            throw new UnapprovedClientAuthenticationException("clientId对应的信息不存在");
        } else if (!passwordEncoder.matches(clientSecret, clientDetails.getClientSecret())) {
            throw new UnapprovedClientAuthenticationException("clientSecret不匹配");
        }
        return clientDetails;
    }
}
